package tabulatorCtrl;

import java.util.Arrays;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import java.text.SimpleDateFormat;
import javax.xml.stream.XMLStreamException;
import electionCtrl.Candidate;
import electionCtrl.Election;
import electionCtrl.Vote;
import xml.MockVotingXMLReader;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.IOException;

public class Tabulator {

	/**
	 * List of candidates who are on "the official ballot"
	 */
	private Candidate [] ballot;
	private int [] numbers;
	private List<Vote> votes;
	private FileWriter fstream; //for file writing
    private BufferedWriter out; //this as well
	
	/**
	 * Create a new Tabulator object given a "ballot"
	 * @param ballot Candidate array... this is somewhat abusive...
	 */
	public Tabulator(Candidate[] ballot, String fileLoc) throws IOException {
		this.ballot = ballot;
		Arrays.sort(this.ballot);
		this.numbers = new int [this.ballot.length];
		this.votes = new LinkedList<Vote>();
		fstream = new FileWriter(fileLoc);
		out = new BufferedWriter(fstream);
	}
	
	public Tabulator(Election election, String fileLoc) throws IOException
	{
		this(election.getCandidates(), fileLoc);
	}
	
	public Tabulator() { //default which dodges a problem with try-catches and scope
		ballot = new Candidate[0];
		Arrays.sort(ballot);
		numbers = new int[ballot.length];
		votes = new LinkedList<Vote>();
	}

	public void addVotes(MockVotingXMLReader reader) throws XMLStreamException
	{
		while (reader.hasNext())
		{
			String next = reader.next();
			if (next.equals("<Vote>"))
			{
				try {
					this.votes.add(new Vote(new Candidate(reader)));
				} catch (IllegalArgumentException e) {
					System.out.println("illegal seat in the .vot xml!");
				}
			}
		}
	}

	/**
	 * Tally some number of votes into an existing Tabulator object.
	 * @param votes Candidate array... this is somewhat abusive...
	 */
	public void addVotes(Vote[] vote) 
	{
		for(int i = 0; i<vote.length; i++)
		{
			this.votes.add(vote[i]);
		}
	}
	
	public void tabulate()
	{
		for(int index = 0; index < this.ballot.length; index++)
		{
			int tally = 0;
			for(Vote vote : this.votes)
			{
				if(vote.candidate.equals(this.ballot[index]))
				{
					tally++;
				}
			}
			this.numbers[index] = tally;
		}
	}

	private static String timeNow(String dateFormat)
	{
		Calendar cal = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
		return sdf.format(cal.getTime());
	}
	
//	/**
//	 * Returns what office the candidate is running for
//	 */
//	private Candidate.Seat candidateType(String candidate)
//	{
//		int start = candidate.indexOf(",");
//		int end = candidate.indexOf(",", start+1);
//		String seatString = candidate.substring(start+1, end);
//		for(Candidate.Seat seat : Candidate.Seat.values())
//		{
//			if(seatString.equals(seat.toString()))
//			{
//				return seat;
//			}
//		}
//		return null;
//	}

	public String printReport() throws IOException
	{
		String d1 = timeNow("MM/dd/yy");
		String d2 = timeNow("H:mm:ss");
		String total = "Created   " + d1 + "   " + d2 + "\n";
//		System.out.print(total);
//		out.write("Created   " + d1 +"   "+ d2);
//		out.newLine();
		Candidate.Seat currentSeat = null;
		for(int i = 0; i < this.ballot.length; i++)
		{
			if(!this.ballot[i].seat.equals(currentSeat))
			{
				currentSeat = this.ballot[i].seat;
				total += "\n*** " + this.ballot[i].seat + " ***\n";
			}
			total += this.ballot[i].name + " has received " + this.numbers[i] + " votes.\n";
//			out.write(this.ballot[i].name + " has received " + this.numbers[i] + " votes.");
//			out.newLine();
		}
		
		System.out.println(total);
		this.out.write(total);
		return total;
	}
	
	public void writeFile() throws IOException {
		out.flush();
		out.close();
	}
}
